using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework;
using DragonAwakening.Core.Graphics;

namespace DragonAwakening.Game
{
    // Texture manager.
    public class TextureManager : ITextureManager
    {
        // Texture container.
        public readonly IDictionary<string, Texture2D> textures = new Dictionary<string, Texture2D>();

        /// <summary>
        /// Solid texture container.
        /// </summary>
        private readonly IDictionary<Color, Texture2D> solidTexturesCache = new Dictionary<Color, Texture2D>();

        /// <summary>
        /// Graphics device.
        /// </summary>
        private readonly GraphicsDevice device;

        // Creates the scene manager.
        public TextureManager(ContentManager content, GraphicsDevice device)
        {
            // Level 3 textures
            this.textures.Add("3T0_1", content.Load<Texture2D>("SceneTextures\\Top0Level3_1"));
            this.textures.Add("3T1_1", content.Load<Texture2D>("SceneTextures\\Top1Level3_1"));
            this.textures.Add("3T2_1", content.Load<Texture2D>("SceneTextures\\Top2Level3_1"));
            this.textures.Add("3T3_1", content.Load<Texture2D>("SceneTextures\\Top3Level3_1"));

            this.textures.Add("3B3_1", content.Load<Texture2D>("SceneTextures\\BottomLevel3_1"));
            this.textures.Add("3S3_1", content.Load<Texture2D>("SceneTextures\\LeftLevel3_1"));
            this.textures.Add("3F3_1", content.Load<Texture2D>("SceneTextures\\FrontLevel3_1"));

            // Character
            this.textures.Add("skull", content.Load<Texture2D>("Characters\\Skull"));
            this.textures.Add("bag_slot", content.Load<Texture2D>("Characters\\BagSlot"));

            this.textures.Add("wall", content.Load<Texture2D>("SceneTextures\\texture-stonewall-low"));
            this.textures.Add("forest", content.Load<Texture2D>("SceneTextures\\texture-forest-wall-low"));
            this.textures.Add("grass", content.Load<Texture2D>("SceneTextures\\texture-green-grass2-low"));

            this.textures.Add("bear1", content.Load<Texture2D>("Monster\\bear_brown"));
            this.textures.Add("wolf", content.Load<Texture2D>("Monster\\Wolf"));
            this.textures.Add("character_info_stats", content.Load<Texture2D>("Characters\\CharacterScreen"));
            this.textures.Add("character_frame", content.Load<Texture2D>("Characters\\CharSelectedFrame"));
            this.textures.Add("character_frame_btn_close", content.Load<Texture2D>("Characters\\CloseButton"));
            this.textures.Add("character_frame_btn_bags", content.Load<Texture2D>("Characters\\BagsButton"));
            this.textures.Add("character_frame_btn_spells", content.Load<Texture2D>("Characters\\SpellsButton"));
            this.textures.Add("character_frame_btn_skills", content.Load<Texture2D>("Characters\\SkillsButton"));
            this.textures.Add("character_frame_btn_melee", content.Load<Texture2D>("Characters\\MeleeButton"));
            this.textures.Add("character_frame_btn_attributes", content.Load<Texture2D>("Characters\\StatsButton"));

            this.textures.Add("character_head_human_male", content.Load<Texture2D>("Characters\\human_male"));
            this.textures.Add("character_head_human_female", content.Load<Texture2D>("Characters\\human_female"));
            this.textures.Add("character_head_dwarf_male", content.Load<Texture2D>("Characters\\dwarf_male"));
            this.textures.Add("character_head_dwarf_female", content.Load<Texture2D>("Characters\\dwarf_female"));
            this.textures.Add("character_head_halfling_male", content.Load<Texture2D>("Characters\\halfling_male"));
            this.textures.Add("character_head_halfling_female", content.Load<Texture2D>("Characters\\halfling_female"));
            this.textures.Add("character_head_halfelf_male", content.Load<Texture2D>("Characters\\halfelf_male"));
            this.textures.Add("character_head_halfelf_female", content.Load<Texture2D>("Characters\\halfelf_female"));
            this.textures.Add("character_head_elf_male", content.Load<Texture2D>("Characters\\elf_male"));
            this.textures.Add("character_head_elf_female", content.Load<Texture2D>("Characters\\elf_female"));
            this.textures.Add("character_head_halforc_male", content.Load<Texture2D>("Characters\\halforc_male"));
            this.textures.Add("character_head_halforc_female", content.Load<Texture2D>("Characters\\halforc_female"));

            this.device = device;
        }

        ///<summary>
        /// Gets the texture.
        ///</summary>
        ///<param name="level">Level of depth of the scene. Values: 4, 3, 2, 1, 0</param>
        ///<param name="position">Texture position: T - top, B - bottom, S - side, F - front.</param>
        ///<param name="family">Texture family. Use 1.</param>
        ///<param name="offset">Texture offset from center, varies depending on the level of depth. 3,2,1,0.</param>
        public Texture2D Get(int level, char position, short family, short offset)
        {
            Texture2D texture;
            string key = string.Concat(level.ToString(), position, offset.ToString(), '_', family.ToString());
            this.textures.TryGetValue(key, out texture);
            return texture;
        }

        /// <summary>
        /// Gets the texture using the texture key.
        /// </summary>
        /// <param name="key">Texture key.</param>
        /// <returns>Texture if available, otherwise null.</returns>
        public Texture2D Get(string key)
        {
            Texture2D texture;
            this.textures.TryGetValue(key, out texture);
            return texture;
        }

        /// <summary>
        /// Constructs solid texture.
        /// </summary>
        /// <param name="color">Texture color.</param>
        /// <returns>Solid texture.</returns>
        public Texture2D GetColorTexture(Color color)
        {
            Texture2D texture = null;
            if (!this.solidTexturesCache.TryGetValue(color, out texture))
            { 
                texture = new Texture2D(device, 1, 1, false, SurfaceFormat.Color);
                texture.SetData(new Color[] { color });
                this.solidTexturesCache.Add(color, texture);
            }

            return texture;
        }
    }
}
